﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace main
{
    class Program
    {
        internal static BlockingCollection<int> _TestBlockCollection = new BlockingCollection<int>(5);

        class ThreadWork1 // producer
        {
            public ThreadWork1() { }

            public void Run()
            {
                Console.WriteLine("ThreadWork1 run...");
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("ThreadWork1 producer:" + i);
                    _TestBlockCollection.Add(i);
                }
                // _TestBlockCollection.CompleteAdding();
                Console.WriteLine("ThreadWork1 run end...");
            }
        }

        class ThreadWork2 // consumer
        {
            public ThreadWork2() { }
            public void Run()
            {
                int i = 0;
                int nCnt = 0;
                bool IsDequeuue = false;
                Console.WriteLine("ThreadWork2 run...");
                while (!_TestBlockCollection.IsCompleted)
                {
                    IsDequeuue = _TestBlockCollection.TryTake(out i);
                    if (IsDequeuue)
                    {
                        Console.WriteLine("ThreadWork1 consumer: " + i * i + "  ====" + i);
                        nCnt++;
                    }
                }
                Console.WriteLine("ThreadWork2 run end...");
            }
        }

        static void StartT1()
        {
            ThreadWork1 work1 = new ThreadWork1();
            work1.Run();
        }

        static void StartT2()
        {
            ThreadWork2 work2 = new ThreadWork2();
            work2.Run();
        }

        static void Main(string[] args)
        {
            /*
            Task task1 = new Task(() => StartT1());
            Task task2 = new Task(() => StartT2());
            _TestBlockCollection = new BlockingCollection<int>();
            Console.WriteLine("Sample 4-4 Main: ");
            Console.WriteLine("Main t1 t2 started: ");
            task1.Start();
            task2.Start();
            Console.WriteLine("Wait t1 t2 end: ");
            Task.WaitAll(task1, task2);
            */
            ProcessQueue<int> processQueue = new ProcessQueue<int>();
            processQueue.ProcessExceptionEvent += ProcessQueue_ProcessExceptionEvent;
            processQueue.ProcessItemEvent += ProcessQueue_ProcessItemEvent;

            processQueue.Enqueue(1);
            processQueue.Enqueue(2);
            processQueue.Enqueue(3);

            Console.ReadKey();
        }

        /// <summary>
        /// 该方法对入队的每个元素进行处理
        /// </summary>
        /// <param name="obj"></param>
        private static void ProcessQueue_ProcessItemEvent(int obj)
        {
            Console.WriteLine(obj);
        }

        /// <summary>
        /// 处理异常
        /// </summary>
        /// <param name="arg1">队列实例</param>
        /// <param name="arg2">异常对象</param>
        /// <param name="arg3">出错的数据</param>
        private static void ProcessQueue_ProcessExceptionEvent(dynamic arg1, Exception arg2, int arg3)
        {
            Console.WriteLine($"{nameof(arg1)}发生错误:{arg2.ToString()},出错的数据:{arg3}");
        }
    }
}
